package com.malex.mxtracker.component;

import com.malex.mxtracker.MxTracker;
import com.malex.mxtracker.bean.Bank;
import com.malex.mxtracker.bean.Project;
import com.malex.mxtracker.bean.ProjectTreeProvider;
import com.malex.mxtracker.component.content.Content;
import com.malex.mxtracker.component.content.SelectableFolderContent;
import com.malex.mxtracker.util.IAction;
import com.malex.mxtracker.util.InverseSet;
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.OddEvenItem;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IDetachable;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import wickettree.TableTree;
import wickettree.provider.ProviderSubset;
import wickettree.table.HeadersToolbar;
import wickettree.table.NoRecordsToolbar;
import wickettree.table.TreeColumn;
import wickettree.theme.HumanTheme;

import java.util.ArrayList;
import java.util.Set;

/**
 * @author Manusovich Alexander
 */
public class ProjectsPanel extends Panel {
    private Content projectsTreeContent;
    private TableTree<Project> projectsTree;
    private Set<Project> projectsTreeState;

    public ProjectsPanel(String id, Project selected) {
        super(id);

        ProjectTreeProvider provider = new ProjectTreeProvider();
        IModel<Project> selectedModel = null;
        if (selected != null) {
            selectedModel = provider.model(selected);
        }
        projectsTreeState = new InverseSet<Project>(new ProviderSubset<Project>(provider));
        projectsTreeContent = new SelectableFolderContent(provider, new IAction<Project>() {
            private static final long serialVersionUID = 1L;

            public void execute(final Project object) {
                PageParameters pageParameters = new PageParameters();
                pageParameters.add("project", "" + object.getId());
                HomePage page = new HomePage(pageParameters);
                setResponsePage(page);
            }
        }, selectedModel);
        projectsTree = createTree(provider, newStateModel());
        projectsTree.add(new HeaderContributor(new IHeaderContributor() {
            private static final long serialVersionUID = 1L;

            public void renderHead(IHeaderResponse response) {
                response.renderCSSReference(new HumanTheme());
            }
        }));
        add(projectsTree);
    }

    protected TableTree<Project> createTree(ProjectTreeProvider provider, IModel<Set<Project>> state) {
        IColumn<Project>[] columns = createColumns();

        projectsTree = new TableTree<Project>("tree", columns, provider, Integer.MAX_VALUE, state) {
            private static final long serialVersionUID = 1L;

            @Override
            protected Component newContentComponent(String id, IModel<Project> model) {
                return ProjectsPanel.this.newContentComponent(id, model);
            }

            @Override
            protected Item<Project> newRowItem(String id, int index, IModel<Project> model) {
                return new OddEvenItem<Project>(id, index, model);
            }
        };
        projectsTree.addTopToolbar(new HeadersToolbar(projectsTree));
        projectsTree.addBottomToolbar(new NoRecordsToolbar(projectsTree));
        return projectsTree;
    }

    protected Component newContentComponent(String id, IModel<Project> model) {
        return projectsTreeContent.newContentComponent(id, projectsTree, model);
    }

    private IModel<Set<Project>> newStateModel() {
        return new AbstractReadOnlyModel<Set<Project>>() {
            @Override
            public Set<Project> getObject() {
                return projectsTreeState;
            }

            /**
             * Super class doesn't detach - would be nice though.
             */
            @Override
            public void detach() {
                ((IDetachable) projectsTreeState).detach();
            }
        };
    }

    @SuppressWarnings("unchecked")
    private IColumn<Project>[] createColumns() {
        ArrayList<IColumn<Project>> columns = new ArrayList<IColumn<Project>>();
        columns.add(new TreeColumn<Project>(Model.of("name")));
        columns.add(new PropertyColumn<Project>(Model.of("incoming"), "incoming") {
            @Override
            public String getCssClass() {
                return "project-incoming";
            }
        });
        columns.add(new PropertyColumn<Project>(Model.of("expense"), "expense") {
            @Override
            public String getCssClass() {
                return "project-expense";
            }
        });
        columns.add(new AbstractColumn<Project>(Model.of("bank")) {
            public void populateItem(Item<ICellPopulator<Project>> cellItem, String componentId,
                                     IModel<Project> rowModel) {
                Long bid = rowModel.getObject().getBank();
                String bankString = "-";
                if (bid != null) {
                    Bank bank = MxTracker.getBanks().get(bid);
                    if (bank != null) {
                        bankString = bank.getName();
                    }
                }
                cellItem.add(new Label(componentId, bankString));
            }

            @Override
            public String getCssClass() {
                return "number";
            }
        });
        columns.add(new PropertyColumn<Project>(Model.of("description"), "description"));
        return columns.toArray(new IColumn[columns.size()]);
    }

}